home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / MacStarter (THINK C 5.0⁄6.0) / applicationProcs.c < prev    next >
Text File  |  1992-10-11  |  27KB  |  525 lines

  1. /* MacStarter is a shell for simple Macintosh applications shell written in
  2.    THINK C, with some small use of its object-oriented features.
  3.    This file is the place to start when you want to write a new application
  4.    with MacStarter.  The whole system is described in a README file that
  5.    should be in the same folder with this file.  There should also be
  6.    sample applicationProc files (kaleidoSketch.c, pentominos.c and
  7.    simpleScroll.c).  Finally, the file uncommentedProcs.c is a copy
  8.    of this file without any comments, in case you would rather use that
  9.    as a starting point.
  10.       To write an application, you need to fill in or modify at least some
  11.    of the functions in this file.  (You should start by copying and renaming
  12.    the file.)  The places in the file where you might need to do some work
  13.    are all commented with comments beginning with //.  Most of them are
  14.    also in the "mark menu" that you see when you hold down the command key
  15.    and press the mouse in the title bar of this window.
  16. */
  17.  
  18.  
  19. #include "globals-MacStarter.h"
  20.  
  21. long gEventWaitTime = 1000000;  // This is used by function WaitNextEvent in the
  22.           // main program as the maximum acceptable time for the program to
  23.           // be "put to sleep" while waiting for the next event.  If your
  24.           // program has an "ApplicationIdle" function, you will need to
  25.           // change this value.  See the comment on that function.  Otherwise,
  26.           // you can ignore gEventWaitTime.
  27.  
  28.  
  29. MenuHandle editMenu, fileMenu;  // These variables are defined to provide a
  30.           // way to refer to the file and edit menus in function UpdataMenus.
  31.           // If you add other menus, you will need to define MenuHandles for
  32.           // them.
  33.  
  34.  
  35. void InitApplication(void);                 // This is a list of the functions
  36. void UpdateMenus(void);                     // defined in this file.  (I have to
  37. void DoEditMenu(int itemNum);               // declare functions before
  38. void DoFileMenu(int itemNum, int* done);    // defining them because I turned 
  39. void DoOtherMenu(int menuID, int itemNum);  // on the "Require Prototypes"
  40. void ApplicationIdle(void);                 // option in the Language Settings
  41. void CleanUpApplication(void);              // panel of the Options dialog.)
  42. void AboutBox(void);
  43. void DoNewCommand(void);
  44.  
  45.  
  46.  
  47. /***********************  Window definition **********************************/
  48.  
  49.  
  50. class myWindow : public xWindow {
  51.  
  52.    // The class xWindow is defined in globals-MacStarter.c.  It provides the
  53.    // basic functionality of Macintosh windows.  You define the behaviour of
  54.    // actual windows in your program by defining the subclass myWindow of
  55.    // class xWindow.  To do this, you just have to say how your window
  56.    // responds to certain events, by filling in the definitions of the
  57.    // functions that are called in response to those events.  The list
  58.    // of functions that you might have to change is given in this
  59.    // "subclass declaration" for myWindow.  The actual functions follow.
  60.    // See the individual functions for more information.
  61.       
  62.    // You will almost certainly need to add some information to this
  63.    // definition of myWindow.  You should insert here the 
  64.    // declarations of any variables you need to hold data relevant
  65.    // to the contents of the window.  These variables should be defined
  66.    // HERE, not as global variables, since each window needs its own
  67.    // version of the variables.  You can also add new functions to the
  68.    // following list of functions.  (NOTE: You can certainly define
  69.    // additional window classes, if your program needs windows with a
  70.    // variety of behaviours.)
  71.    
  72.  public:
  73.    virtual void OpenInRect(Str255 title, int left, int top, int right, int bottom);   
  74.    virtual short Close(void);
  75.    
  76.  protected:  // (Note: You will never actually CALL these functions directly;
  77.              //  just define what they do.)
  78.    virtual void SetDefaults(void);
  79.    virtual void doKey(char ch);
  80.    virtual void doContentClick(Point localPt);
  81.    virtual void adjustToNewSize(void);
  82.    virtual void doRedraw(Rect* badRect);
  83.    virtual void doHScroll(int dh);
  84.    virtual void doVScroll(int dv);
  85.    virtual void doActivate(int active);
  86.    
  87. };
  88.  
  89.  
  90. // Function SetDefaults is called automatically when a new window is opened,
  91. // BEFORE the actual window is created.  It sets up the appearance of the
  92. // window and initializes variables associated with the window.  This function 
  93. // should always START by calling inherited::SetDefaults, which sets up the
  94. // default appearance and behaviour.  THEN, you can make any changes you
  95. // want. 
  96. //    The inherited function gives default values to the variables
  97. // features, topScrollOffset, bottomScrollOffset, leftScrollOffset,
  98. // rightScrollOffset, minH, minV, maxH, maxV, hLinesPerPage and 
  99. // vLinesPerPage.  The most important of these is FEATURES, which
  100. // determines whether or not the window has a go-away box, a zoom box,
  101. // a grow box, a horizontal scroll bar, and a vertical scroll bar.  Its
  102. // default value is hasGoAway + hasZoom + hasGrow + hasHScroll + hasVScroll,
  103. // which will produce a window with all possible features.  If you want
  104. // only a subset of features, you should set the value of features
  105. // appropriately.  For example,  features = hasGoAway  will produce a
  106. // non-resizable, unscrollable window with a go-away box in the upper left 
  107. // corner that the user can click on to close the window.
  108. //    You will probably not need to worry about the other varaibles,
  109. // but, for the record:  minH, minV, maxH and maxV determine how big
  110. // and how small the user can make the window by dragging the grow box in
  111. // the lower right corner of the window.  The defaults allow very large and
  112. // very small values.  The range of allowable horizontal sizes  for the window is
  113. // from minH to maxH, and for vertical sizes is minV to maxV.  You might well
  114. // want to change minH and minV to prevent really small windows.  You
  115. // can set minH to have the same value as maxH.  In that case, the window
  116. // can only be resized vertically.  (But be sure that the window is first
  117. // opened at the correct size!)  If your window has a maximum size, it should
  118. // not have a zoom box, since zooming will not respect the maximum size.
  119. //    When a user clicks in the gray region of a scroll bar, the window
  120. // should scroll by a greater amount than when the user clicks in an
  121. // arrow.  The variables hLinesPerPage and vLinesPerPage control this 
  122. // behaviour.  By definition, a click in the gray area of the horizontal scroll
  123. // bar is equivalent to hLinesPerPage clicks on one of the horizontal scroll's
  124. // arrows.  Similarly for vLinesPerPage.  Usually, the correct values
  125. // for these variables depend on the size of the window, so they would
  126. // ordinarily be reset in function adjustToNewSize().
  127. //     By default, the window's scroll bars will extend all the way across,
  128. // or up and down, the window.  Sometimes, you might want to leave some
  129. // space at one end or another of a scroll bar.  If so, you can set
  130. // the value of one of the variables topScrollOffset, bottomScrollOffset, 
  131. // leftScrollOffset or rightScrollOffset.  These work in what should be
  132. // a obvious way.
  133.  
  134. void myWindow::SetDefaults(void) {
  135.    inherited::SetDefaults();
  136.    // Make changes to defaults. You also can initialize the window's data.
  137.    // Most likely change is erase some of the items on the right of:
  138.    // features = hasHScroll + hasVScroll + hasGoAway + hasZoom + hasGrow;
  139. }
  140.  
  141.  
  142. // Function OpenInRect is called whenever a window needs to be opened. It should
  143. // start by calling the default inherited::OpenInRect, which actually opens
  144. // the window (including calling SetDefaults in turn).  After this, you can
  145. // do any further initialization your window might need.  (Most initialization
  146. // can be done in SetDefaults, but when SetDefaults is called, the actual
  147. // window doesn't exist yet.  In some cases, such as installing a TEdit or
  148. // a Control, you need the actual window.  These things can be done in the
  149. // function below, after the call to inherited::OpenInRect.  The variable
  150. // that points to the Mac window data structure is called  theWindow.)
  151.  
  152. void myWindow::OpenInRect(Str255 title, int left, int top, int right, int bottom) {
  153.    inherited::OpenInRect(title,left,top,right,bottom);
  154.    // insert any additional initialization of window data here.
  155. }
  156.  
  157.  
  158. // Function myWindow::Close is called when the window is closing (for example,
  159. // when the user clicks in its GoAway box). If you have any dynamically allocated
  160. // variables in the window, this is the place to delete their storage.
  161. // It is ESSENTIAL that the call to inherited::Close be the LAST thing in
  162. // this function.  (This function is declared to return a short in case you
  163. // want a Close function that can "refuse to close" by returning a value
  164. // of zero.  Typically, you might ask if the user wants to save the window
  165. // contents before closing, and you might provide a CANCEL option that
  166. // should abort the closing.  If the window is closing because the user
  167. // chose QUIT from the file menu, you will need to know that the user
  168. // decided to cancel.  You could then call the close function like this:
  169. // if ( win->Close() ) ... )
  170.  
  171. short myWindow::Close(void) {
  172.    // Clean-up before closing window.
  173.    inherited::Close();  // You can't refer to any window data after this call !
  174.    return 1;  // not used in the existing program
  175. }
  176.  
  177.  
  178. // Function doKey is called when the user types any character.  The character
  179. // typed is passed as the parameter ch.  If you want to get at the actual
  180. // event record that generated this function call, you can find it in the
  181. // global variable gEvent.  You can, for example, check whether the user
  182. // was holding down the option key by checking:
  183. // if ( gEvent.modifiers & optionKey ) ...  Note that command key events
  184. // are NOT sent to this function.  They are automatically intercepted and
  185. // changed into menu events.
  186. //    NOTE: Before this function is called, the "graphics port" is set to
  187. // this window.  That just means that ANY drawing you do in this function
  188. // will apply to this window.
  189.  
  190. void myWindow::doKey(char ch) {
  191.    // Handle key-click
  192. }
  193.  
  194.  
  195. // Function doContentClick is called when your program needs to respond to
  196. // a user clicking the mouse on this widow.  (Clicks on scroll bars, grow
  197. // boxes, etc, are handled automatically and are NOT sent to this function.
  198. // Also, when the user clicks on an inactive window, that click is handled
  199. // by activating the window and is NOT sent to this function.)  The coordinates
  200. // of the point where the user clicked are sent in the parameter localPt.
  201. // These coordinates are in the window's local coordinates (in which the
  202. // top, left corner is (0,0) unless you have changed them).  You can get
  203. // full information about the mouse-down event from the global variable
  204. // gEvent.  For example, "if (gEvent.modifiers & cmdKey)..." will test
  205. // whether the user was holding down the command key when the mouse was clicked.
  206. // In addition, the global variable gClickCount can be used to determine
  207. // whether this is a double click; this variable is set to 1 for a single
  208. // click, to 2 for the second click of a double click, to 3 for the third
  209. // click of a triple click, etc.  For a double click, for example, this function
  210. // gets BOTH clicks in succession, with gClickCount set to 1 the first
  211. // time and to 2 the second time.  (Also NOTE:  The Macintosh toolbox function
  212. // StillDown() will be true as long as the user continues to hold down the
  213. // mouse key.  You might, for example, use a  while (StillDown()) loop to
  214. // follow the mouse or perform some action as long as the user holds down
  215. // the button.)
  216. //    NOTE: Before this function is called, the "graphics port" is set to
  217. // this window.  That just means that ANY drawing you do in this function
  218. // will apply to this window.
  219.  
  220. void myWindow::doContentClick(Point localPt) {
  221.    // Handle a mouse click
  222. }
  223.  
  224.  
  225. // Function doRedraw is called when the window, or a portion of it, needs to
  226. // be redrawn (because the window has been resized or moved from behind
  227. // another window, for example.)  It is also called when the window is
  228. // first opened (after all the initialization done in SetDefaults and
  229. // OpenInRect).  Note that your window always needs to save enough data
  230. // to redraw itself (if you want your application to act like a real Mac program).
  231. // Ordinarily, you will simply redraw the entire contents of the window.
  232. // However, if your window is very complicated, you might save some time
  233. // by using the parameter badRect.  This is a rectangle that contains the
  234. // portion of the window that actually needs to be redrawn.
  235. //    If your window uses scroll bars, you will need to know the current
  236. // settings and maximums on those scroll bars.  You can find out by
  237. // calling the functions GetHVal(), GetVVal(), GetHMax() and GetVMax().
  238. //    (People sometimes have trouble understanding this function.  It has to
  239. // exist because the Mac doesn't actually remember what's in your window.
  240. // When one window covers another, anything in the bottom window is forgotten
  241. // When the window is later uncovered, the Mac sticks you with the 
  242. // responsibility of remembering what was there and reconstituting it.
  243. // So, ordinarily, this function is redoing old work rather than getting
  244. // new work done.  This imposes the great burden on the programmer of
  245. // remembering what's in each window.)
  246. //    NOTE: Before this function is called, the "graphics port" is set to
  247. // this window.  That just means that ANY drawing you do in this function
  248. // will apply to this window.
  249.  
  250. void myWindow::doRedraw(Rect* badRect){
  251.    // redraw current contents of window.
  252. }
  253.  
  254.  
  255. // Function adjustToNewSize is called whenever the window changes size because
  256. // the user drags its grow box or clicks its zoom box.  If you need to make
  257. // any changes to accomodate the new size, do it here.  However, DO NOT
  258. // redraw the window here; function doRedraw() is going to be called 
  259. // automatically after this function to do the actual redrawing.
  260. // The inherited function simply resizes and moves the scroll bars, if any.
  261. // After this, you might need to readjust the values, maximums or
  262. // linesPerPage associated with the scroll bars.  The functions SetHVal(),
  263. // SetVVal(), SetHMax(), SetVMax(), SetHLinesPerPage() and SetVLinesPerPage()
  264. // can be used to change these settings.  If you have TEdits or
  265. // controls of your own, they will have to be resized and moved.  If the
  266. // stuff drawn in the window needs to be scaled to the new size, you can do
  267. // it here.
  268.  
  269. void myWindow::adjustToNewSize(void) {
  270.    inherited::adjustToNewSize();
  271.    // respond to change in window size
  272. }
  273.  
  274.  
  275. // Function doHScroll is called when the user changes the position of the
  276. // horizontal scroll.  It will be called repeatedly if the user holds down the
  277. // mouse button on an arrow or in the gray area of the scroll.  The inherited
  278. // function simply erases the sreen and then calls your DoRedraw() function
  279. // to redraw the screen contents (presumably reflecting the new position of
  280. // the scroll).  Depending on your application, this might be fine, but it
  281. // can cause an annoying flicker and can be too time-consuming.  If you
  282. // want to change this, you should ERASE the call to inherited::doHScroll
  283. // and substitute your own code.  (Typically, you will call the Mac
  284. // Toolbox routine ScrollRect() and then just do the minimal redrawing
  285. // necessary.)  The parameter tells the CHANGE in the value of the horizontal
  286. // scroll.  You can get the actual new value by calling GetHVal().
  287.  
  288. void myWindow::doHScroll(int dh) {
  289.    inherited::doHScroll(dh);  // replace with your own code if you
  290.                               // don't like the default behaviour
  291. }
  292.  
  293.  
  294. // Function doVScroll is called when the user changes the position of the
  295. // vertical scroll.  Similar comments to those on doHScroll() apply.
  296.  
  297. void myWindow::doVScroll(int dv) {
  298.    inherited::doVScroll(dv);  // replace with your own code if you
  299.                               // don't like the default behaviour
  300. }
  301.  
  302.  
  303. // Function doActivate is called when your window is deactivated (because
  304. // the user clicks on another window) or activated (because the user clicks
  305. // on this window and it is being moved to the front).  The inherited
  306. // function takes care of activating or deactivating the scroll bars.  If
  307. // your window has its own control or TEdit, you can activate or deactivate
  308. // them here.  Otherwise, there is probably nothing that this function
  309. // needs to do.  (In particular, this function does NOT redraw the window.)
  310. // The parameter "active" is 0 if the window is being deactivated and is
  311. // non-zero if it is being activated.
  312.  
  313. void myWindow::doActivate(int active) {
  314.    inherited::doActivate(active);
  315.    // activate/deactivate controls, TEdits, etc.  (if any)
  316. }
  317.  
  318.  
  319. /****************************************************************************/
  320.  
  321.  
  322. // Function InitApplication is called when the application first starts up.
  323. // It should be used to initialize any global variables that require
  324. // initialization.  Here, it is also used to open the first window
  325. // of the program.
  326.  
  327. void InitApplication(void) {
  328.   MenuHandle appleMenu;
  329.   fileMenu = GetMHandle(2);  // get handles to the menus, for use in UpdateMenus
  330.   editMenu = GetMHandle(3);
  331.   appleMenu = GetMHandle(1); // Note that your program is not responsible for 
  332.                              // managing the apple menu, except to set the
  333.                              // program name in the first line of the
  334.                              // menu, as is done in the next line.
  335.   SetItem(appleMenu,1,"\pAbout Generic...");
  336.   DoNewCommand();  // opens a window.
  337. }
  338.  
  339.  
  340. // Function UpdateMenus() is called just before any user action directed at the
  341. // menu bar is processed.  That is, it is called when the user clicks in
  342. // the menu bar (but before the user sees any menus), or when the user
  343. // command-presses a keyboard key (but before that command is looked up
  344. // in the menus).  The purpose of this function is to enable and
  345. // disable commands as appropriate.  A command that is "disabled" is
  346. // grayed out in the menu and is unavaialble to the user.  For example,
  347. // if there is no window open, then the Close Window command should
  348. // certainly be disabled.  The function UpdateMenus should set the
  349. // enable/disable status of any menu item whose status can change.
  350. // (In the existing program's file menu, for example, the New and
  351. // Quit commands are always enabled.  The Close command is enabled and
  352. // disabled as appropriate by this function.)
  353. //     The Edit menu is a special case.  This menu is supposed to be
  354. // available, with all its standard commands enabled, if the front window
  355. // on the screen belongs to a desk accessory rather than to your program.
  356. // This is handled by the first few lines of the function below, which
  357. // you should not change.  You should also not insert new items into
  358. // the edit menu, except at the end, after the standard items.
  359.  
  360. void UpdateMenus(void) {
  361.  
  362.    short i;
  363.    WindowPtr win;  // pointer to macintosh window data structure
  364.    xWindow *xwin;  // pointer to xWindow data structure
  365.  
  366.    win = FrontWindow();   // this is the front window on the screen
  367.  
  368.    if ( win && ((WindowPeek)win)->windowKind < 0 ) {  // Desk accessory window
  369.       EnableItem(editMenu,1);          // Do not change this section.
  370.       for (i=3; i<7; i++)              // This has nothing to do with
  371.          EnableItem(editMenu,i);       // your program
  372.    }
  373.    else {   // enable/disable edit item menus as relevant to your program
  374.       DisableItem(editMenu,1);
  375.       for (i=3; i<7; i++)         // Here, I just disable them all
  376.          DisableItem(editMenu,i);
  377.    }
  378.  
  379.    if (win && xWindow::Window2XWindow(win,&xwin)) {  //if front window is mine...
  380.       EnableItem(fileMenu,2);  // enable Close command
  381.    }
  382.    else {
  383.       DisableItem(fileMenu,2); // disable Close command
  384.    }
  385. }
  386.  
  387.  
  388. // Function DoEditMenu is called if the user selects a command from the
  389. // Edit menu.  (By default, these commands are disabled, so this function
  390. // won't be called unless you enable them in function UpdateMenus().)
  391. // The parameter gives the item number of the command, counting from the
  392. // top of the menu.
  393.  
  394. void DoEditMenu(int itemNum) {
  395.    // handle command from edit menu
  396. }
  397.  
  398.  
  399. // Function DoFileMenu() is called if the user selects a command from the
  400. // File menu.  The parameter itemNum gives the number of the command counting
  401. // down from the top of the menu.  NOTE that if you insert items into the
  402. // menu, the command numbers for the existing commands will change, and these
  403. // changes will have to be reflected in the if statements in this function.
  404. // The parameter "done" should be set to 1 if the user chooses QUIT from the
  405. // file menu; however, you have the possibility of ABORTING this command
  406. // simply by not setting this value.  (For example, you might as the user
  407. // if she wants to save her data before quitting and she might click on the
  408. // cancel button in the dialog box.)
  409.  
  410. void DoFileMenu(int itemNum, int* done) {
  411.    xWindow *win;
  412.    // Handle file menu commands:
  413.    if (itemNum == 4)
  414.       *done = 1;
  415.    else if (itemNum == 1)
  416.       DoNewCommand();
  417.    else if (itemNum == 2 && xWindow::Window2XWindow(FrontWindow(),&win))
  418.       win->Close();
  419. }
  420.  
  421.  
  422. // If you have added other menus besides the Apple, File and Edit menus,
  423. // this function will be called when the user chooses a command from
  424. // such a menu.  The parameters tell you the menu and the number of the
  425. // item in the menu.  Note that the first parameter is the menuID,
  426. // NOT the position of the menu in the menu bar.  (If the menu comes out
  427. // of a resource file, the menuID is the resource number; if you create it
  428. // "on the fly", you set the menuID when you create it.)
  429.  
  430. void DoOtherMenu(int menuID, int itemNum) {
  431.    // handle command (from menu other than apple, file or edit menu)
  432. }
  433.  
  434.  
  435. // Function ApplicationIdle is called periodically while your program is
  436. // running.  Specifically, it is called each time an "event" is generated
  437. // by the user or by the operating system.  User events include mouse and
  438. // key clicks.  Operating system events are things like window-activation
  439. // events.  In addition, if no other event occurs, the operating system
  440. // can send a "null" event.  The purpose of such an event is exactly to
  441. // make sure that a function like ApplicationIdle gets called sufficiently
  442. // often.  The frequency of null events is determined by the global
  443. // varialble gEventWaitTime.  If you put anything into this function,
  444. // you should change the value of this variable at the top of this
  445. // file.  gEventWaitTime is measured in 1/60-ths of a second.  It represents
  446. // the maximum time that you would like between calls to ApplicationIdle.
  447. // (It is not a guaranteed that the operating system will always be able to
  448. // meet this deadline; it depends on what else is going on in the system.)
  449. //    One common use of ApplicationIdle is to set the cursor style to reflect
  450. // the part of the screen that the mouse is currently over.  If you do this,
  451. // a value of gEventWaitTime of about 3 seems to work well.
  452. //    Another use is to allow the null events to "drive" a long computation
  453. // or an animation.  If you just go ahead and do an animation, say, with a
  454. // long for loop, there will be no way for the user to interrupt it.  It is
  455. // better to use ApplicationIdle to do just one frame of an animation or
  456. // one small piece of a computation.  Of course, this is much more difficult--
  457. // you need to keep track of what you are doing in global variables or
  458. // window data variables.  Anyway, if you do do this, you should set
  459. // gEventWaitTime to 0.  This just asks the operating system to spend
  460. // as little time as possible away from your program.
  461. //    If your program uses a TEdit (This is a standard Mac text edit box),
  462. // Then you should call TEIdle in this function and set gEventwaitTime
  463. // to a value no greater than about 10.
  464. //     The reason for not automatically setting gEventWaitTime to a small
  465. // value is that the operating system can give time to other programs
  466. // running in the background if there is nothing for your program to do.
  467.  
  468. void ApplicationIdle(void) {
  469.    // Perform any periodic task required by your program
  470. }
  471.  
  472.  
  473. // Function CleanUpApplication is called just before the program ends normally.
  474. // You will probably have nothing to do here, especially since there is
  475. // no way to abort the program termination, but, just in case...
  476.  
  477. void CleanUpApplication(void) {
  478. }
  479.  
  480.  
  481. // Function AboutBox is called when the user chooses the first item in the 
  482. // Apple menu, usually a command of the form "About <program-name>...".
  483. // It should display information about your program.  This default
  484. // version simply displays a box that has four fill-in-the-blank areas
  485. // that are set by the call to ParamText().  You can just make changes
  486. // to this.  However, if you happen to use this shell to write a serious
  487. // program, you will want to do something different.  For one thing, this
  488. // method is totally insecure.  Since it just uses one of the resources in
  489. // the resource file MacStarter.π.rsrc, anyone who wanted to steal credit
  490. // for your program could do so by editing its resource fork with ResEdit.
  491. // (It would be better to open a window and draw into it directly.)
  492. //    Note:  The \r's in the third line here represent line breaks.  There
  493. // is room for three fairly short lines in this field, which is meant for
  494. // your address (although, of course, you can use it for whatever you want).
  495.  
  496. void AboutBox(void) {
  497.    // Set up program name, author name, address, short program description.
  498.    ParamText( "\pGeneric Application",
  499.               "\pDavid Eck",
  500.               "\pHobart and William Smith College\rGeneva, NY   14456\rE-mail: eck@hws.bitnet",
  501.               "\pThis program can be used as a shell for creating Macintosh Applications.");
  502.    Alert(128,0L);
  503. }
  504.  
  505.  
  506. // Function DoNewCommand is called from DoFileMenu above when the user chooses
  507. // the New command from the file menu.  In this sample program, it is also
  508. // called when the program is first started up.  It simply creates
  509. // and opens a window.  Here, win->Open(title) will open a window that is
  510. // about 3/4 the size of the screen in each dimension.  Each successive
  511. // window will be slightly offset from the previous one.  You could also
  512. // open the window with win->OpenFullScreen(title), which will open a window
  513. // that fills the entire screen.  Or, win->OpenInRect(title,L,t,r,b) will
  514. // open a window in a specified rectangle.  In this case, the window extends
  515. // from L to r horizontally and from t to b vertically.  L, t, r and b are
  516. // measured in screen coordinates, in which the top left corner of the 
  517. // screen is (0,0).  (Actually, L, t, r, and b specify the position of the
  518. // inside of the window only, not including the title bar or a 1-pixel border
  519. // around the window.)
  520.  
  521. void DoNewCommand(void) {
  522.    myWindow *win;
  523.    win = new myWindow;  // (this create window storage space before opening it)
  524.    win->Open("\pSample Window");  // need a better window title!
  525. }